package com.forg.mvc.core.plugin;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.forg.mvc.core.common.ClassUtil;
import com.forg.mvc.core.common.Constant;

@Plugin(name="quartzPlugin")
public class QuartzPlugin {
    
    private static final Logger logger = LoggerFactory.getLogger(QuartzPlugin.class);
    
    private final String config = "job.properties";
    
    private static final String CLASS = "class";
    private static final String ENABLE = "enable";
    private static final String CRON = "cron";
    private static final String GROUP = "group";
    private static final String DEFAULT_GROUP = "DEFAULT_GROUP";
    
    private Properties properties;
    
//    private SchedulerFactory schedulerFactory;
    private Scheduler scheduler;
    
    @SuppressWarnings("unchecked")
    public void init(){
        loadProperties();
        
        try {
//            schedulerFactory = new StdSchedulerFactory();
//            scheduler = schedulerFactory.getScheduler();
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            
            Enumeration<Object> enums = properties.keys();
            while (enums.hasMoreElements()) {
                
                try {
                    String key = enums.nextElement() + "";
                    
                    //not set class or not enable. 
                    if(!key.endsWith(CLASS) || !isTrue(getJobKey(key, ENABLE))){
                        continue;
                    }
                    
                    String jobClassName = properties.get(key) + "";
                    String jobName  =     key.substring(0,key.indexOf(Constant.DOT));
                    String jobCronExp =   properties.getProperty(getJobKey(key,CRON)) + "";
                    String jobGroup     = properties.getProperty(getJobKey(key,GROUP,DEFAULT_GROUP));
                    
                    Class<? extends Job> jobClass = null;
                    try {
                        jobClass = (Class<? extends Job>) Class.forName(jobClassName);
                    } catch (ClassNotFoundException e) {
                        logger.error("init class [" +jobClassName +"] error!",e);
                        continue;
                    }
                    
                    JobDetail job = JobBuilder.newJob(jobClass)
                            .withIdentity(jobName, jobGroup).build();
                    CronTrigger trigger = TriggerBuilder
                            .newTrigger()
                            .withIdentity(jobName + "-trigger", jobGroup)
                            .withSchedule(
                                    CronScheduleBuilder.cronSchedule(jobCronExp))
                            .build();
                
                    scheduler.scheduleJob(job, trigger);
                    
                } catch (SchedulerException e) {
                    logger.error(e.getMessage());
                    
                    continue;
                }
            }
            
            scheduler.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        
        logger.debug("init QuartzPlugin done.");
    }
    
    
    private void loadProperties() {
        
        try {
            properties = new Properties();
            InputStream is = ClassUtil.getClassLoader().getResourceAsStream(config);
            properties.load(is);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        
    }
    
    private String getJobKey(String str,String type,String defaultValue) {
        String key = getJobKey(str,type);
        
        if (key == null || "".equals(key.trim()))
            return defaultValue;
        
        return key;
    }
    
    private String getJobKey(String str,String type) {
        return str.substring(0, str.lastIndexOf(CLASS)) + type;
    }
    
    private boolean isTrue(String key) {
        if(properties.get(key) == null) 
            return false;
        
        String enable = (properties.get(key) + "").trim();
        
        if("true".equalsIgnoreCase(enable)
                || "y".equalsIgnoreCase(enable)){
            return true;
        }
        
        return true;
    }

}
